#pragma once

#include "base/core/singleton.h"
#include "base/core/object_pool.h"
#include "base/core/gamemath.h"
#include "Common/ComDefine.pb.h"
#include "Common/TableData/ItemItemCfg.h"
#include "Common/TableData/EquipEquipCfg.h"
#include "Common/PackageDefine.h"
#include "Common/Item/Item.h"
#include "Common/DropDefine.h"


typedef bool(*CompareFunc)(CItemBase*, CItemBase*);
typedef bool(*CompareDupFunc)(const ItemProtoInfo &protoA, const ItemProtoInfo &protoB);
class ItemMgr : public ManualSingleton<ItemMgr>
{
	friend class ManualSingleton<ItemMgr>;
public:	
	ItemMgr();
	virtual ~ItemMgr();
	bool Init();
	void UnInit();
	//生成新物品对象
	CItemBase *MakeItemObj(uint8_t byLabel);
	//释放物品对象
	bool FreeItemObj(CItemBase *pItemObj);
	//获取标签页排序比较函数指针
	CompareFunc *GetCompareFunc(uint8_t byLabel);
	//获取副本比较函数
	CompareDupFunc *GetDupFunc();
	//使用物品
	//int32_t UseItem(/ *uint32_t nItemID* /CItemBase *item, uint16_t nNum, Creature *pMaster, UseItemArgProto &arg);*/
	//创建物品
	bool CreateItem(LIST_ITEM &lstItem, VEC_ITEM_PROTO_EX &vecProtoEx, SItemCond &itemCond, bool bMerge = true);
	//创建物品
	bool CreateItem(VEC_ITEM_PROTO &vecProtoItems, VEC_PACKAGE_ITEM &vecItems);
	//创建物品
	bool CreateItem(VEC_ITEM_PROTO_EX &vecProtoItemsEx, VEC_PACKAGE_ITEM &vecItems);

	/////////////////////////////////  掉落物品 /////////////////////////////////////////
	//创建掉落物品
	bool CreateDropItem(uint32_t nDropID, VEC_ITEM_PROTO_EX &vecProtoEx, VEC_UINT32 &vecDropGold,SItemCond &itemCond, int32_t itemReduce = DROP_RAND_BASE_NUM, int32_t goldReduce = DROP_RAND_BASE_NUM);
	/////////////////////////////////////// 宝箱掉落 ///////////////////////////////////
	//创建宝箱掉落物品 nBoxID：box表中drop表ID
	bool CreateBoxDropItem(uint32_t nBoxID, VEC_ITEM_PROTO_EX &vecProtoEx, int32_t &goldNum, int32_t &diamondNum, int32_t &bindDiamond, BoxCondCfg &boxCond, int32_t nNum = 1, bool bMerge = true);
	//创建宝箱掉落物品 nBoxID：box表中drop表ID
	bool CreateBoxDropItem(uint32_t nBoxID, LIST_ITEM &lstItem, int32_t &goldNum, int32_t &diamondNum, int32_t &bindDiamond, BoxCondCfg &boxCond, int32_t nNum = 1);
	//根据条件获取宝箱掉落的子ID nBoxID：box表中drop表ID
	bool GetBoxSonIdByCond(uint32_t nBoxID, BoxCondCfg &boxCond, int32_t &boxSonId);
	//创建宝箱子掉落物品 nBoxSonID:box表 son 表ID
	bool CreateBoxSonDropItem(uint32_t nBoxSonID, LIST_ITEM &lstItem, int32_t &goldNum, int32_t &diamondNum, int32_t &bindDiamond, int32_t nNum = 1);
	//创建宝箱子掉落物品 nBoxSonID:box表 son 表ID
	bool CreateBoxSonDropItem(uint32_t nBoxSonID, VEC_ITEM_PROTO_EX &vecProtoEx, int32_t &goldNum, int32_t &diamondNum, int32_t &bindDiamond, int32_t nNum = 1, bool bMerge = true);
	//创建角色装备
	void CreateCharEquip(CharacterDBInfo &req);

	//转盘掉落
	bool ZhuanPanDropItem(uint32_t nBoxID, LIST_UINT32& lstGrid, LIST_ITEM &lstItem, int32_t nNum);

	//////////////////////////////////////////////////////////////////////////

	//设置物品信息
	bool SetItemProtoInfo(LIST_ITEM &lstItem, VEC_ITEM_PROTO_EX &vecProto,SItemCond &itemCond);
	//设置物品protobuf信息
	bool SetItemProtoInfo(CItemBase *pItem, ItemProtoInfo *protoItem, int32_t nNum = -1);
	//背包添加物品后物品的绑定状态
	int8_t BindStateByAdd(uint32_t nItemId, int8_t byBind);
	int8_t BindStateByAdd(const ItemItemCfgInfo *pItemCfg, int8_t byBind);
	int8_t BindStateByAdd(const EquipEquipCfgInfo *pEquipCfg, int8_t byBind);
	//穿戴装备后装备的绑定状态
	int8_t BindStateByDress(uint32_t nItemId,int8_t byBind);
	int8_t BindStateByDress(const EquipEquipCfgInfo *pEquipCfg, int8_t byBind);
	//获取物品堆叠数
	int32_t ItemMaxPile(uint32_t itemId);
	int32_t ItemMaxPile(const ItemItemCfgInfo *pItemCfg);
	int32_t ItemMaxPile(const EquipEquipCfgInfo *pEquipCfg);
	//获取玩法开放等级 强化 精炼 镶嵌 符文
	uint32_t GetOpenLel(uint32_t constant_id);
	//是否有效的绑定途径
	bool ValidBindWay(int8_t bindWay);
	//是否有效的禁止类型
	bool ValidForbidType(int8_t forbidType);
	//是否有效的物品属性初始化类型
	bool ValidInitAttrType(int8_t initAttrType);
	//物品是否能交易
	bool CanTrade(uint32_t itemId,int8_t byInBind);
	//物品能否出售
	bool CanSell(uint32_t itemId,int8_t byInBind);
	//物品能否死亡掉落  byDestory:是否掉落直接销毁
	bool CanDieDrop(uint32_t itemId,int8_t byInBind);
	//获取背包标签页
	uint8_t GetPackageLabel(uint32_t nItemId);
	uint8_t GetPackageLabel(const ItemItemCfgInfo *pItemCfg);
	uint8_t GetPackageLabel(const EquipEquipCfgInfo *pEquipCfg);
		//是否是任务物品
	bool IsTaskItem(uint32_t itemId);
private:
	//物品排序比较函数
	static bool CompareSundryFunc(CItemBase *pItemA, CItemBase *pItemB);
	static bool CompareMaterialFunc(CItemBase *pItemA, CItemBase *pItemB);
	static bool CompareTaskFunc(CItemBase *pItemA, CItemBase *pItemB);
	static bool CompareEquipFunc(CItemBase *pItemA, CItemBase *pItemB);
	//副本拾取物品排序
	static bool CompareDuplicateFunc(const ItemProtoInfo &protoA, const ItemProtoInfo &protoB);
	//创建物品
	bool CreateItem(LIST_ITEM &lstItem, VEC_PACKAGE_ITEM &vecItems, SItemCond &itemCond, bool bMerge = true);
	//宝箱物品
	bool BoxDropItem(uint32_t nBoxID, LIST_ITEM &lstItem, int32_t &goldNum, int32_t &diamondNum, int32_t &bindDiamond, BoxCondCfg &boxCond, int32_t nNum = 1);
	//宝箱子掉落物品
	bool BoxSonDropItem(uint32_t nBoxSonID, LIST_ITEM &lstItem, int32_t &goldNum, int32_t &diamondNum, int32_t &bindDiamond, int32_t nNum = 1);
	//合并物品
	void MergeItem(LIST_ITEM &lstItem, LIST_ITEM &lstOutItem);
	//校验物品
	bool CheckItem(VEC_ITEM_PROTO_EX &vecProtoItems);
	//设置出生装备
	bool SetBornEquipProto(int8_t byPos, uint32_t nItemId, CharacterDBEquipData *protoEquip);
private:
	ObjectPool<CItem>	*m_pItemPool;
	ObjectPool<CEquip>  *m_pEquipPool;  
	CompareFunc m_CompareFunc[EPackageLabel_limit];
	CompareDupFunc m_CompareDupFunc;
	MAP_INT32_INT32 m_openLelMap;
};

#define g_MakeItemMgr() (ItemMgr::Instance())
#define g_GetItemMgr()  (ItemMgr::GetInstance())
#define g_DelItemMgr()  (ItemMgr::Destroy())
